function Observer() {
	this._evtGroup = [];
}

Observer.prototype = {
	subscribe : function(eventName, eventHandler, constArgs) {
		var handlers = this._evtGroup[eventName];

		if (!handlers)
			handlers = this._createEventName(eventName);

		var context = this;

		if (this.subscribers) {
			this.subscribers[eventName] = eventHandler;
			for ( var item in handlers) {
				if (item._fn === eventHandler)
					return this;
			}
		}

		var handler = function() {
			return eventHandler.apply(context, constArgs || arguments);
		}
		handler._fn = eventHandler;

		this._appendHandler(handlers, handler);
		return this;
	},
	unsubscribe : function(eventName, eventHandler) {
		var handlers = this._evtGroup[eventName];
		if (!handlers)
			return false;

		return this._removeHandler(handlers, eventHandler);
	},
	publish : function(eventName, args, context) {
		var handlers = this._evtGroup[eventName];
		if (!handlers)
			return;

		var temp = handlers;
		var j = temp.length;
		this._evtGroup[eventName] = [];

		for ( var i = 0; i < j; i++) {
			var curr = temp.shift();
			this._evtGroup[eventName].push(curr);
			if (curr.apply( {}, args || []) === false) {
				this._evtGroup[eventName] = this._evtGroup[eventName]
						.concat(temp);
				return false;
			}
		}
		return true;
	},
	_createEventName : function(eventName) {
		if (!this._evtGroup[eventName]) {
			this._evtGroup[eventName] = [];
		}
		return this._evtGroup[eventName];
	},
	_appendHandler : function(handlers, eventHandler) {
		var j = handlers.length;
		for ( var i = 0; i < j; i++) {
			if (handlers[i]._fn === eventHandler._fn)
				return false;
		}

		handlers.push(eventHandler);
		return true;
	},
	_removeHandler : function(handlers, eventHandler) {
		var j = handlers.length;
		if (!eventHandler)
			handlers = [];

		for ( var i = 0; i < j; i++) {
			var curr = handlers.shift();
			if (curr._fn == eventHandler)
				return true;
			handlers.push(curr);
		}
		return false
	}
};

/*******************************************************************************
 * ** Decorator Implementation ***
 ******************************************************************************/

if (!window.GT) {
	window.GT = {};
}

GT.Observer=GT.Observer || {};
GT.Observer = new Observer;